<?php

/**
 * DOMIT Utilities are a set of utilities for the DOMIT! parser
 * @package domit-xmlparser
 * @copyright (C) 2004 John Heinstein. All rights reserved
 * @license http://www.gnu.org/copyleft/lesser.html LGPL License
 * @author John Heinstein <johnkarl@nbnet.nb.ca>
 * @link http://www.engageinteractive.com/domit/ DOMIT! Home Page
 * DOMIT! is Free Software
 * */
/**
 * @global Array Translation table for predefined XML entities
 */
$GLOBALS['DOMIT_PREDEFINED_ENTITIES'] = array('&' => '&amp;', '<' => '&lt;', '>' => '&gt;',
    '"' => '&quot;', "'" => '&apos;');

/**
 * A set of utilities for the DOMIT! parser
 *
 * These methods are intended to be called statically
 *
 * @package domit-xmlparser
 * @author John Heinstein <johnkarl@nbnet.nb.ca>
 */
class DOMIT_Utilities {

    /**
     * Raises an error if an attempt to instantiate the class is made
     */
    function DOMIT_Utilities() {
        die("DOMIT_Utilities Error: this is a static class that should never be instantiated.\n" .
                "Please use the following syntax to access methods of this class:\n" .
                'DOMIT_Utilities::methodName(parameters)');
    }

//DOMIT_Utilities

    /**
     * Generates a normalized (formatted for readability) representation of the node and its children
     * @param Object The root node of the narmalization
     * @param boolean True if illegal xml characters in text nodes and attributes should be converted to entities
     * @return string The formatted string representation
     */
    static function toNormalizedString(&$node, $subEntities=false, $definedEntities) {
        $node_level = 0;
        $response = '';

        //$node is a DOMIT_Document
        if ($node->nodeType == DOMIT_DOCUMENT_NODE) {
            $total = $node->childCount;

            for ($i = 0; $i < $total; $i++) {
                $response .= DOMIT_Utilities::getNormalizedString($node->childNodes[$i],
                                $node_level, $subEntities, $definedEntities);
            }

            return $response;
        } else {
            return ($response . DOMIT_Utilities::getNormalizedString($node,
                    $node_level, $subEntities, $definedEntities));
        }
    }

//toNormalizedString

    /**
     * Converts illegal XML characters to their entity representations
     * @param string The text to be formatted
     * @param array User defined translation table for entities
     * @return string The formatted text
     */
    static function convertEntities($text, $definedEntities) {
        global $DOMIT_PREDEFINED_ENTITIES;
        $result = strtr($text, $DOMIT_PREDEFINED_ENTITIES);
        $result = strtr($result, $definedEntities);
        return $result;
    }

//convertEntities

    /**
     * Gets a normalized (formatted for readability) representation of the current node
     * @param Object The node to be normalized
     * @param int The level in the DOM hierarchy where the node is located
     * @param boolean True if illegal xml characters in text nodes and attributes should be converted to entities
     * @param array User defined translation table for entities
     * @return string The normalized string representation
     */
    static function getNormalizedString(&$node, $node_level, $subEntities=false, $definedEntities) {
        $response = '';

        switch ($node->nodeType) {
            case DOMIT_ELEMENT_NODE:
                $response .= DOMIT_Utilities::getNormalizedElementString($node, $response,
                                $node_level, $subEntities, $definedEntities);
                break;

            case DOMIT_TEXT_NODE:
                if ($node->nextSibling == null) {
                    $node_level--;
                }

                $response .= ( $subEntities ?
                                DOMIT_Utilities::convertEntities($node->nodeValue, $definedEntities) :
                                $node->nodeValue);
                break;

            case DOMIT_CDATA_SECTION_NODE:
                if ($node->nextSibling == null) {
                    $node_level--;
                }

                $response .= '<![CDATA[' . $node->nodeValue . ']]>';
                break;

            case DOMIT_ATTRIBUTE_NODE:
                $response .= $node->toString(false, $subEntities);
                break;

            case DOMIT_DOCUMENT_FRAGMENT_NODE:
                $total = $node->childCount;

                for ($i = 0; $i < $total; $i++) {
                    $response .= DOMIT_Utilities::getNormalizedString($node->childNodes[$i], $node_level,
                                    $subEntities, $definedEntities);
                }

                break;

            case DOMIT_COMMENT_NODE:
                $response .= '<!--' . $node->nodeValue . '-->';

                if ($node->nextSibling == null) {
                    $node_level--;
                }

                $response .= DOMIT_Utilities::getIndentation($node_level);

                break;

            case DOMIT_PROCESSING_INSTRUCTION_NODE:
                $response .= '<' . '?' . $node->nodeName . ' ' . $node->nodeValue . '?' . '>';

                if ($node->nextSibling == null) {
                    $node_level--;
                }

                $response .= DOMIT_Utilities::getIndentation($node_level);

                break;

            case DOMIT_DOCUMENT_TYPE_NODE:
                $response .= $node->toString() . "\n";
                break;
        }

        return $response;
    }

//getNormalizedString

    /**
     * Gets a normalized (formatted for readability) representation of the current element
     * @param Object The node to be normalized
     * @param string The current normalized text
     * @param int The level in the DOM hierarchy where the node is located
     * @param boolean True if illegal xml characters in text nodes and attributes should be converted to entities
     * @param array User defined translation table for entities
     * @return string The normalized string representation
     */
    static function getNormalizedElementString(&$node, $response, $node_level, $subEntities, $definedEntities) {
        $response .= '<' . $node->nodeName;

        //get attributes text
        if (is_object($node->attributes)) { //DOMIT
            $response .= $node->attributes->toString(false, $subEntities);

            /*
              if ($node->ownerDocument->isNamespaceAware) {
              foreach ($node->namespaceURIMap as $key => $value) {
              $response .= ' xmlns:' . $value . '="' . $key . '"';
              }
              }
             */
        } else { //DOMIT_Lite
            foreach ($node->attributes as $key => $value) {
                $response .= ' ' . $key . '="';
                $response .= ( $subEntities ? DOMIT_Utilities::convertEntities($value,
                                        $definedEntities) : $value);
                $response .= '"';
            }
        }

        $node_level++;

        //if node is childless
        if ($node->childCount == 0) {
            if ($node->ownerDocument->doExpandEmptyElementTags) {
                if (in_array($node->nodeName, $node->ownerDocument->expandEmptyElementExceptions)) {
                    $response .= ' />';
                } else {
                    $response .= '></' . $node->nodeName . '>';
                }
            } else {
                if (in_array($node->nodeName, $node->ownerDocument->expandEmptyElementExceptions)) {
                    $response .= '></' . $node->nodeName . '>';
                } else {
                    $response .= ' />';
                }
            }
        } else {
            $response .= '>';

            //get children
            $myNodes = & $node->childNodes;
            $total = $node->childCount;

            //no indentation if first child is a text node
            if (!DOMIT_Utilities::isTextNode($node->firstChild)) {
                $response .= DOMIT_Utilities::getIndentation($node_level);
            }

            for ($i = 0; $i < $total; $i++) {
                $child = & $myNodes[$i];
                $response .= DOMIT_Utilities::getNormalizedString($child, $node_level,
                                $subEntities, $definedEntities);
            }

            $response .= '</' . $node->nodeName . '>';
        }

        $node_level--;

        if ($node->nextSibling == null) {
            $node_level--;
            $response .= DOMIT_Utilities::getIndentation($node_level);
        } else {
            //no indentation if next sibling is a text node
            if (!DOMIT_Utilities::isTextNode($node->nextSibling)) {
                $response .= DOMIT_Utilities::getIndentation($node_level);
            }
        }

        return $response;
    }

//getNormalizedElementString

    /**
     * Determines whether the specified node is a Text node
     * @param Object The node to be tested
     * @return boolean True if the node is a Text node
     */
    static function isTextNode(&$node) {
        $type = $node->nodeType;
        return (($type == DOMIT_TEXT_NODE) || ($type == DOMIT_CDATA_SECTION_NODE));
    }

//isTextNode

    /**
     * Returns the indentation required for the specified node level
     * @param int The current node level
     * @return string The indentation required for the specified node level
     */
    static function getIndentation($node_level) {
        $INDENT_LEN = '    ';
        $indentation = "\n";

        for ($i = 0; $i < $node_level; $i++) {
            $indentation .= $INDENT_LEN;
        }

        return $indentation;
    }

//getIndentation

    /**
     * Removes the extension from the specified file name
     * @param string The file name
     * @return string The file name, stripped of its extension
     */
    static function removeExtension($fileName) {
        $total = strlen($fileName);
        $index = -1;

        for ($i = ($total - 1); $i >= 0; $i--) {
            if ($fileName{$i} == '.') {
                $index = $i;
            }
        }

        if ($index == -1) {
            return $fileName;
        }

        return (substr($fileName, 0, $index));
    }

//removeExtension

    /**
     * Determines whether the XML string is valid (NOT FULLY IMPLEMENTED!)
     * @param string The XML text
     * @return boolean True if the XML text is valid
     */
    static function validateXML($xmlText) {
        //this does only rudimentary validation
        //at this point in time
        $isValid = true;

        if (is_string($xmlText)) {
            $text = trim($xmlText);

            switch ($text) {
                case '':
                    $isValid = false;
                    break;
            }
        } else {
            $isValid = false;
        }

        return $isValid;
    }

//validateXML

    /**
     * Set the browser header to interpret data as UTF-8 formatted
     * @param string The content type of the data
     */
    static function printUTF8Header($contentType = 'text/html') {
        echo header('Content-type: ' . $contentType . '; charset=utf-8');
    }

//printUTF8Header

    /**
     * Formats a string for presentation as HTML
     * @param string The string to be formatted
     * @param boolean True if the string is to be sent directly to output
     * @return string The HTML formatted string
     */
    static function forHTML($text, $doPrint = false) {
        if ($doPrint) {
            print ('<pre>' . htmlspecialchars($text) . '</pre>');
        } else {
            return ('<pre>' . htmlspecialchars($text) . '</pre>');
        }
    }

//forHTML

    /**
     * Generates a node tree from an array and appends it to the specified document or node
     * @param object The document or node to which the child nodes should be appended
     * @param array An associative multidimensional array of elements and values
     */
    static function fromArray(&$node, &$myArray) {
        if ($node->nodeType == DOMIT_DOCUMENT_NODE) {
            $docNode = & $node;
        } else {
            $docNode = & $node->ownerDocument;
        }

        foreach ($myArray as $key => $value) {
            if (is_array($value)) {
                //check for numeric indices
                $total = count($value);

                if (($total > 0) && isset($value[0])) {
                    for ($i = 0; $i < $total; $i++) {
                        $node->appendChild($docNode->createElement($key));
                        DOMIT_Utilities::fromArray($node->lastChild, $value[$i]);
                    }
                } else {
                    //generate child elements
                    $node->appendChild($docNode->createElement($key));
                    DOMIT_Utilities::fromArray($node->lastChild, $value);
                }
            } else {
                $node->appendChild($docNode->createElement($key));
                $node->lastChild->appendChild($docNode->createTextNode($value));
            }
        }
    }

//fromArray

    static function parseAttributes() {
        
    }

//parseAttributes
}

//DOMIT_Utilities
?>